import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { API_CONFIG, HTTP_STATUS, ERROR_MESSAGES } from './config';
import type { BaseResponse, RequestOptions, ErrorModel } from './types';

// 创建取消令牌存储
const pendingMap = new Map<string, AbortController>();

// 创建 axios 实例
const instance: AxiosInstance = axios.create({
  baseURL: API_CONFIG.baseURL,
  timeout: API_CONFIG.timeout,
  headers: API_CONFIG.headers,
});

// 生成请求键
const generateReqKey = (config: AxiosRequestConfig) => {
  const { method, url, params, data } = config;
  return [method, url, JSON.stringify(params), JSON.stringify(data)].join('&');
};

// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 获取 token
    const token = localStorage.getItem('token');
    if (token) {
      config.headers = config.headers || {};
      config.headers.Authorization = `Bearer ${token}`;
    }

    // 添加 API 前缀，但要避免重复添加
    if (config.url && !config.url.startsWith('http') && !config.url.startsWith(API_CONFIG.prefix)) {
      config.url = `${API_CONFIG.prefix}${config.url}`;
    }

    // 处理重复请求
    const controller = new AbortController();
    config.signal = controller.signal;
    const requestKey = generateReqKey(config);
    
    if (pendingMap.has(requestKey)) {
      pendingMap.get(requestKey)?.abort();
      pendingMap.delete(requestKey);
    }
    pendingMap.set(requestKey, controller);

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  (response: AxiosResponse) => {
    const requestKey = generateReqKey(response.config);
    pendingMap.delete(requestKey);

    const { status } = response;
    if (status === HTTP_STATUS.SUCCESS) {
      return response;
    }
    return Promise.reject(new Error(response.data.message || ERROR_MESSAGES.default));
  },
  async (error) => {
    if (axios.isCancel(error)) {
      return Promise.reject(new Error('请求已取消'));
    }

    const config = error.config;
    
    // 处理重试逻辑
    if (config?.retryTimes && config.retryTimes > 0) {
      config.retryTimes--;
      
      // 延迟重试
      await new Promise(resolve => setTimeout(resolve, config.retryDelay || API_CONFIG.retry.retryDelay));
      
      return instance(config);
    }

    // 错误处理
    const errorInfo: ErrorModel = {
      code: error.response?.status || 500,
      message: error.response?.data?.message || ERROR_MESSAGES.default,
    };

    // 处理特定错误
    switch (errorInfo.code) {
      case HTTP_STATUS.UNAUTHORIZED:
        // 处理未授权
        errorInfo.message = ERROR_MESSAGES.unauthorized;
        break;
      case HTTP_STATUS.TIMEOUT:
        errorInfo.message = ERROR_MESSAGES.timeout;
        break;
    }

    return Promise.reject(errorInfo);
  }
);

// 请求函数封装
export const request = async <T = any>(
  config: AxiosRequestConfig,
  options: RequestOptions = {}
): Promise<T> => {
  const { retryTimes = API_CONFIG.retry.maxRetries, retryDelay = API_CONFIG.retry.retryDelay } = options;

  const finalConfig = {
    ...config,
    retryTimes,
    retryDelay,
  };

  try {
    const response = await instance.request<any, BaseResponse<T>>(finalConfig);
    return response.data;
  } catch (error) {
    return Promise.reject(error);
  }
};

// 导出请求方法
export const http = {
  get: <T = any>(url: string, params?: any, options?: RequestOptions) =>
    request<T>({ method: 'GET', url, params }, options),
    
  post: <T = any>(url: string, data?: any, options?: RequestOptions) =>
    request<T>({ method: 'POST', url, data }, options),
    
  put: <T = any>(url: string, data?: any, options?: RequestOptions) =>
    request<T>({ method: 'PUT', url, data }, options),
    
  delete: <T = any>(url: string, params?: any, options?: RequestOptions) =>
    request<T>({ method: 'DELETE', url, params }, options),
};

export default instance; 